package com.cq.hd.order.render.impl;

import com.cq.hd.common.enums.biz.ActiveRedPacketStateEnum;
import com.cq.hd.common.enums.biz.DiscountStateEnum;
import com.cq.hd.common.enums.biz.RedPacketTypeEnum;
import com.cq.hd.common.response.Throw;
import com.cq.hd.order.api.dto.CreateOrderDto;
import com.cq.hd.order.render.OrderContext;
import com.cq.hd.order.render.OrderRenderStepEnum;
import com.cq.hd.order.render.dto.PriceDetailDto;
import com.cq.hd.order.service.TbOrderService;
import com.cq.hd.product.api.TbActiveRedPacketBillApi;
import com.cq.hd.product.api.dto.ActiveDiscountSonDto;
import com.cq.hd.product.api.vo.ActiveRedPacketBillPageVo;
import com.cq.hd.product.api.vo.ActiveVo;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 优惠折扣
 *
 * @author much
 * @since 2024/09/12 22:38
 */
@Component
public class DiscountRender extends AbstractRenderStep {

    @Resource
    private TbOrderService orderService;
    @Resource
    private TbActiveRedPacketBillApi activeRedPacketBillApi;

    @Override
    public OrderRenderStepEnum step() {
        return OrderRenderStepEnum.DISCOUNT;
    }

    @Override
    public void render(OrderContext orderContext) {
        ActiveVo activeVo = orderContext.getActiveVo();
        CreateOrderDto createOrderDto = orderContext.getCreateOrderDto();
        PriceDetailDto priceDetailDto = orderContext.getPriceDetailDTO();
        // 多件多折
        renderDiscount(activeVo, createOrderDto, priceDetailDto);
        // 红包
        renderRedPackage(orderContext, activeVo, createOrderDto, priceDetailDto);
    }

    private void renderDiscount(ActiveVo activeVo, CreateOrderDto createOrderDto, PriceDetailDto priceDetailDto) {
        // 活动是否有开启多件多折规则，有就提取折扣
        Integer discountState = activeVo.getDiscountState();
        if (!DiscountStateEnum.OPEN.getValue().equals(discountState)) {
            return;
        }
        // 多件多折列表(团购)
        List<ActiveDiscountSonDto> activeDiscounts = activeVo.getActiveDiscount();

        // 根据活动id查找多件多折配置
        if (!CollectionUtils.isEmpty(activeDiscounts)) {
            // 根据件数倒序
            activeDiscounts = activeDiscounts.stream()
                    .sorted(Comparator.comparing(ActiveDiscountSonDto::getNum).reversed())
                    .collect(Collectors.toList());
            for (ActiveDiscountSonDto activeDiscountVo : activeDiscounts) {
                Integer num = activeDiscountVo.getNum();
                if (createOrderDto.getOrderNum() >= num) {
                    BigDecimal discount = activeDiscountVo.getDiscount()
                            .divide(new BigDecimal("10"), 4, RoundingMode.HALF_UP);
                    priceDetailDto.setDiscountRate(discount);
                    break;
                }
            }
        }
    }

    private void renderRedPackage(OrderContext orderContext, ActiveVo activeVo, CreateOrderDto createOrderDto, PriceDetailDto priceDetailDto) {
        // 校验红包数据
        Integer totalOrderCount = orderService.userActiveOrderCount(createOrderDto.getUserId(), createOrderDto.getActiveId());
        BigDecimal orderPrice = activeVo.getActivePrice().multiply(new BigDecimal(String.valueOf(createOrderDto.getOrderNum())));
        ActiveRedPacketBillPageVo activeRedPacketBillPageVo = getRedPacketBill(
                createOrderDto.getRedPacketBillId(), createOrderDto.getUserId(), createOrderDto.getActiveId(), totalOrderCount, orderPrice);
        BigDecimal redPacketAmt = BigDecimal.ZERO;
        if (activeRedPacketBillPageVo != null) {
            orderContext.setActiveRedPacketBillPageVo(activeRedPacketBillPageVo);
            redPacketAmt = activeRedPacketBillPageVo.getAmt();
        }
        priceDetailDto.setRedPacketAmt(redPacketAmt);
    }

    public ActiveRedPacketBillPageVo getRedPacketBill(Long redPacketBillId, Long userId, Long activeId, Integer totalOrderCount, BigDecimal orderPrice) {
        if (redPacketBillId == null || redPacketBillId <= 0) {
            return null;
        }

        ActiveRedPacketBillPageVo activeRedPacketBillPageVo = activeRedPacketBillApi.getById(redPacketBillId).unpack();
        if (activeRedPacketBillPageVo == null || !Objects.equals(activeRedPacketBillPageVo.getUserId(), userId)) {
            Throw.isBusinessException("未找到红包数据");
        }

        // 判断红包是否可以在该活动使用
        Long getActiveId = activeRedPacketBillPageVo.getActiveId();
        if (getActiveId > 0 && !activeId.equals(getActiveId)) {
            Throw.isBusinessException("红包不能用于该活动");
        }

        // 能否使用新用户红包
        Integer redPacketType = activeRedPacketBillPageVo.getRedPacketType();
        if (redPacketType.equals(RedPacketTypeEnum.NEW_USER.getValue())) {
            if (totalOrderCount != null && totalOrderCount > 0) {
                Throw.isBusinessException("你已经不是新用户，无法使用新用户红包");
            }
        }

        // 是否达到满减金额
        BigDecimal fullAmount = activeRedPacketBillPageVo.getFullAmount();
        if (fullAmount != null && fullAmount.compareTo(BigDecimal.ZERO) > 0) {
            if (orderPrice.compareTo(fullAmount) < 0) {
                Throw.isBusinessException("订单金额未达到该红包的使用门槛金额【" + fullAmount.stripTrailingZeros().toPlainString() + "元】");
            }
        }

        // 判断是否已被使用
        Integer state = activeRedPacketBillPageVo.getState();
        if (ActiveRedPacketStateEnum.YES_UES.getValue().equals(state) || ActiveRedPacketStateEnum.YES_VERIFY.getValue().equals(state)) {
            Throw.isBusinessException("红包已被使用");
        }

        // 判断是否已过期
        if (ActiveRedPacketStateEnum.YES_EXPIRE.getValue().equals(state)) {
            Throw.isBusinessException("红包已过期");
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expireTime = activeRedPacketBillPageVo.getExpireTime();
        if (now.compareTo(expireTime) >= 0) {
            Throw.isBusinessException("红包已过期");
        }

        activeRedPacketBillPageVo.setState(ActiveRedPacketStateEnum.YES_UES.getValue());
        activeRedPacketBillPageVo.setUseTime(now);

        return activeRedPacketBillPageVo;
    }

}
